﻿using System;
using System.Collections.Generic;
using System.Text;
using Development.Tools;
using System.Net;


namespace Development.Network.Http
{
    public class HttpServer
    {
        protected HttpListener m_listener = null;

        protected Dictionary<string, HttpRoute> m_routes = new Dictionary<string, HttpRoute>();


        protected string m_url = null;

        public const string ResponseError =  
            "<html><head><meta http-equiv= Content-Type content=text/html; charset=utf-8 /><title>亲，您想找什么啊</title></head><body><b>亲，您想找什么啊</b></body></html>";

        
        public void AddRoute(string routeName,HttpRoute route)
        {
            if(!m_routes.ContainsKey(routeName))
            {
                m_routes.Add(routeName, route);
            }
        }

        public bool StartServer(string url)
        {
            m_listener = new HttpListener();
            try
            {
                m_url = url;
                m_listener.Prefixes.Add(url);
                m_listener.Start();
                Log.WriteLog(ELogLevel.LOG_INFO, "http listen success url = " + url.ToString());

                for (int i = 0; i < 20; i++)
                {
                    PostAccept();
                }

                return true;
            }
            catch (Exception e)
            {
                Log.WriteLog(ELogLevel.LOG_ERROR, string.Format("{0};info[instance:{1}methed:{2}stack:{3}", e.Message, e.Source, e.TargetSite.Name, e.StackTrace));
                return false;
            }
        }

        protected void PostAccept()
        {
            IAsyncResult result = m_listener.BeginGetContext(OnRecv, null);
        }

        protected void OnRecv(IAsyncResult result)
        {
            HttpListenerContext context = null;
            try
            {
                context = m_listener.EndGetContext(result);
                ProcessRequst(context);
            }
            catch(Exception)
            {
               
            }
            finally
            {
                PostAccept();
            }
           
        }

        protected void ProcessRequst(HttpListenerContext context)
        {
            HttpListenerRequest request = context.Request;
            string RemoteAddress = request.RemoteEndPoint.ToString();

            HttpListenerResponse response = context.Response;
            string routeString = request.RawUrl;
            int index = request.RawUrl.IndexOf('?');
            if(index != -1)
            {
                routeString = request.RawUrl.Remove(index, request.RawUrl.Length - index);
            }
            if(m_routes.ContainsKey(routeString))
            {
                try
                {
                    bool ret = m_routes[routeString].Process(request, response);
                    if (!ret)
                    {
                        byte[] responseBytes = Encoding.UTF8.GetBytes(ResponseError);
                        response.Close(responseBytes, true);
                    }
                }
                catch(Exception e)
                {
                    byte[] responseBytes = Encoding.UTF8.GetBytes(ResponseError);
                    Log.WriteLog(ELogLevel.LOG_ERROR, e.Message);
                    Log.WriteLog(ELogLevel.LOG_ERROR, "illegality address = " + RemoteAddress);
                    response.Close(responseBytes, true);
                }
             
            }
            else
            {
                Log.WriteLog(ELogLevel.LOG_INFO, "not find route = " + routeString);
                Log.WriteLog(ELogLevel.LOG_ERROR, "illegality address = " + RemoteAddress);
                byte[] responseBytes = Encoding.UTF8.GetBytes(ResponseError);
                response.Close(responseBytes, true);
            
            }
        }

        public void CloseListen()
        {
            m_listener.Close();
        }

    }




}
